﻿using Core.Framework;
using DotNetty.Framework;
using DotNetty.Framework.BaseTriggers;
using DotNetty.OrleansClient;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Groups;
using Grain.Interfaces;
using iTool.ClusterComponent;
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;

namespace iTool.Connector
{
    public class WebSocketEventTriggered<TMessage> : IWebSocketEventTriggered<TMessage>
        where TMessage : AbstractMessage
    {

        WebSocketTaskHandler taskHandlerEvent;
        iToolConnectorProvider iClient;
        ILogger<WebSocketEventTriggered<TMessage>> logger;

        public WebSocketEventTriggered(WebSocketTaskHandler taskHandlerEvent, ILogger<WebSocketEventTriggered<TMessage>> logger)
        {
            this.logger = logger;
            this.taskHandlerEvent = taskHandlerEvent;
            iClient = ProviderOfServices.GetService<iToolConnectorProvider>();
        }

        public async Task OnClose(IChannelHandlerContext context)
        {
            try
            {
                await this.OnClose(context.Channel);
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, "OnClose");
            }
        }

        public async Task OnClose(IChannel context)
        {
            var channel = context.GetChannel();

            iToolClusterHostClient cluster = this.iClient.GetClusterClient();
            if (!string.IsNullOrWhiteSpace(channel))
            {
                // 用户下线
                var channelService = cluster.GetService<IChannelService>(channel);
                await channelService.Offline(AppSetting.iToolConfigure.Ip);
                // 清除用户信息
                context.ClearChannel();
            }

            var clientInfo = context.ClearClientUUID();
            if (clientInfo != null && !string.IsNullOrWhiteSpace(clientInfo?.UUID))
            {
                // 断开连接
                var iCloudConnectionStatistics = cluster.GetService<IConnectionStatisticsService>();
                //, context.Id
                await iCloudConnectionStatistics.Disconnect(AppSetting.iToolConfigure.Ip, clientInfo);
            }
        }

        public async Task OnConnect(IChannelHandlerContext context)
        {
            try
            {
                iToolClusterHostClient cluster = this.iClient.GetClusterClient();
                // 新连接
                var iCloudConnectionStatistics = cluster.GetService<IConnectionStatisticsService>();
                var clientInfo = context.GetClientUUID();
                if (clientInfo != null && !string.IsNullOrWhiteSpace(clientInfo?.UUID))
                {
                    LoggerUtils.Write("OnConnect:" + clientInfo.TryToJson());

                    await iCloudConnectionStatistics.Connection(AppSetting.iToolConfigure.Ip, clientInfo);
                }
            }
            catch (Exception ex)
            {
                LoggerUtils.Write(ex.Message);
            }
        }

        public async Task OnError(IChannelHandlerContext context, OnExceptionContext exceptionContext)
        {
            this.logger.LogError(exceptionContext.Exception, "OnError");

            try
            {
                if (context?.Channel?.Active == true)
                {
                    await context.WriteAndFlushAsyncOfBinaryAsync(exceptionContext.Exception.Message);
                }
                else
                {
                    //await this.OnClose(context);
                }
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, "OnError2");
            }
        }

        public async Task OnMessage(IChannelHandlerContext context, TMessage message)
        {
            if (message == null)
            {
                return;
            }

            try
            {
                // 通知模式
                if (message.Handel == ChanneHandelEnum.Notify)
                {
                    // 接收用户Channel否是有效
                    if (!string.IsNullOrWhiteSpace(message.ToChannel))
                    {
                        // 客户端信息
                        var channel = context.GetChannel();
                        var response = new DoWorkResponse();

                        if (string.IsNullOrWhiteSpace(channel))
                        {
                            response.Token = message.Token;
                            response.Code = CodeResult.PARAMS_IS_INVALID;
                            response.Body = "Channel is null";
                            response.TaskRunTimeOfMilliseconds = 1;
                            if (context.Channel.Active & context.Channel.IsWritable)
                            {
                                await context.WriteAndFlushAsyncOfBinaryAsync(response);
                            }
                            return;
                        }

                        iToolClusterHostClient cluster = this.iClient.GetClusterClient();
                        // 获取 recive channel Grain
                        var iNotifyService = cluster.GetService<INotifyService>(message.ToChannel);
                        await iNotifyService.Publish(message.Parameter, channel);

                        response.Token = message.Token;
                        response.Code = CodeResult.SUCCESS;
                        response.Body = 1;
                        response.TaskRunTimeOfMilliseconds = 1;
                        if (context.Channel.Active & context.Channel.IsWritable)
                        {
                            await context.WriteAndFlushAsyncOfBinaryAsync(response);
                        }
                    }
                }

                // 命令模式
                else if (message.Handel == ChanneHandelEnum.Command)
                {
                    await this.taskHandlerEvent.CommandAsync(context, message);
                }
            }
            catch (Exception ex)
            {
                this.logger.LogError(ex, message.Handel.ToString());

                var response = new DoWorkResponse();
                response.Token = message.Token;
                response.Code = CodeResult.BUSINESS_ERROR;
                response.Body = ex.Message;
                response.TaskRunTimeOfMilliseconds = 0;
                if (context.Channel.Active & context.Channel.IsWritable)
                {
                    await context.WriteAndFlushAsyncOfBinaryAsync(response);
                }
            }

        }

        public async Task OnSendMessage(IChannelGroup group, string messageOfString)
        {
            await group?.WriteAndFlushAsyncOfBinaryAsync(messageOfString);
        }

        public Task UserEventTriggered(IChannelHandlerContext context, object evt)
        {
            return Task.CompletedTask;
            //if (evt is IdleStateEvent eventState)
            //{
            //    if (eventState.State == IdleState.ReaderIdle)
            //    {
            //        this.CloseAsync(context);
            //    }
            //}
            //else if (evt is CloseWebSocketFrame frame)
            //{

            //    this.CloseAsync(context, frame);
            //}
            //else
            //{
            //    base.UserEventTriggered(context, evt);
            //}
        }
    }
}
